#include "channel.hpp"

void downLoad()
{

    std::cout << "downLoad" << std::endl;
}
void print()
{
    std::cout << "print" << std::endl;
}

enum
{
    UsageError = 1,
    PipeError,
    ForkError
};

class processPool
{
public:
    processPool(int n, work_t w) : num(n), func(w)
    {
        channels.reserve(num);
    }
    void debugPrint()
    {
        for (auto &x : channels)
        {
            std::cout << x.name() << std::endl;
        }
    }
    int initProcess()
    {
        for (int i = 1; i <= num; i++)
        {
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
                return PipeError;
            // create 进程
            pid_t id = fork();
            if (id < 0)
                return ForkError;
            // 3. 创建信道
            if (id == 0)
            {
                // 关闭历史 fd
                for (auto c : channels)
                    c.close();

                ::close(pipefd[1]); // read
                // child
                dup2(pipefd[0], 0);
                worker();
                exit(0);
            }

            // 父进程执行
            ::close(pipefd[0]); // write

            channels.emplace_back(pipefd[1], id);
            // zdl:: 4.
        }

        return 0;
    }

    void dispatchTask()
    {
        int who = 0;
        //  2. 派发任务
        while (true)
        {
            // a. 选择一个任务
            int task = tm.selectTask();

            // b. 选择一个子进程
            Channel &curr = channels[who++];
            who %= channels.size();

            std::cout << "############" << std::endl;
            std::cout << "send: " << task << " to " << curr.name() << std::endl;
            std::cout << "############" << std::endl;
            //  派发任务
            curr.send(task);
            sleep(2);
        }
    }
    ~processPool()
    {
        clearProcess();
    }

private:
    std::vector<Channel> channels;
    int num;
    work_t func;
    void clearProcess()
    {
        // zdl:: 经过后面的解释我们就清楚，在进行子进程创建是，子进程会
        // 继承父进程的文件表，就会使前面的父进程的文件表管道多出来，
        // 因此从后往前删除，久能处理这样的问题

        for (int i = channels.size() - 1; i >= 0; i--)
        {
            Channel &x = channels[i];
            x.close();
            pid_t rid = ::waitpid(x.Id(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child " << rid << " wait succes ..." << std::endl;
            }
        }
    }
};